/**
 * JsBarcode 条形码生成工具类
 * 基于JsBarcode库，适配微信小程序环境
 */

// 导入JsBarcode库的核心功能
// 由于小程序环境限制，我们需要手动引入必要的编码模块

/**
 * Code 128 编码表
 */
const CODE128_PATTERNS = [
  "11011001100", "11001101100", "11001100110", "10010011000", "10010001100",
  "10001001100", "10011001000", "10011000100", "10001100100", "11001001000",
  "11001000100", "11000100100", "10110011100", "10011011100", "10011001110",
  "10111001100", "10011101100", "10011100110", "11001110010", "11001011100",
  "11001001110", "11011100100", "11001110100", "11101101110", "11101001100",
  "11100101100", "11100100110", "11101100100", "11100110100", "11100110010",
  "11011011000", "11011000110", "11000110110", "10100011000", "10001011000",
  "10001000110", "10110001000", "10001101000", "10001100010", "11010001000",
  "11000101000", "11000100010", "10110111000", "10110001110", "10001101110",
  "10111011000", "10111000110", "10001110110", "11101110110", "11010001110",
  "11000101110", "11011101000", "11011100010", "11011101110", "11101011000",
  "11101000110", "11100010110", "11101101000", "11101100010", "11100011010",
  "11101111010", "11001000010", "11110001010", "10100110000", "10100001100",
  "10010110000", "10010000110", "10000101100", "10000100110", "10110010000",
  "10110000100", "10011010000", "10011000010", "10000110100", "10000110010",
  "11000010010", "11001010000", "11110111010", "11000010100", "10001111010",
  "10100111100", "10010111100", "10010011110", "10111100100", "10011110100",
  "10011110010", "11110100100", "11110010100", "11110010010", "11011011110",
  "11011110110", "11110110110", "10101111000", "10100011110", "10001011110",
  "10111101000", "10111100010", "11110101000", "11110100010", "10111011110",
  "10111101110", "11101011110", "11110101110", "11010000100", "11010010000",
  "11010011100", "1100011101011"
];

/**
 * Code 128 字符集B映射表 (ASCII 32-127)
 */
const CODE128B_CHARS = {};
for (let i = 32; i <= 126; i++) {
  CODE128B_CHARS[String.fromCharCode(i)] = i - 32;
}

class JsBarcodeUtil {
  /**
   * 生成Code 128条形码
   * @param {Object} canvas - 微信小程序canvas对象
   * @param {string} text - 要编码的文本
   * @param {Object} options - 配置选项
   */
  static generateCode128(canvas, text, options = {}) {
    const defaultOptions = {
      width: 2,
      height: 100,
      displayValue: false,
      fontSize: 12,
      fontFamily: 'monospace',
      textAlign: 'center',
      textPosition: 'bottom',
      textMargin: 2,
      background: '#ffffff',
      lineColor: '#000000',
      margin: 10,
      marginTop: 10,
      marginBottom: 10,
      marginLeft: 10,
      marginRight: 10
    };

    const config = Object.assign({}, defaultOptions, options);
    
    try {
      // 验证输入文本
      if (!text || typeof text !== 'string') {
        throw new Error('文本不能为空且必须是字符串');
      }

      // 验证字符是否在Code 128B范围内
      for (let char of text) {
        if (!(char in CODE128B_CHARS)) {
          throw new Error(`字符 "${char}" 不在Code 128B支持范围内`);
        }
      }

      console.log('[JsBarcodeUtil] 开始生成条形码:', text);

      // 编码数据
      const encodedData = this.encodeCode128B(text);
      console.log('[JsBarcodeUtil] 编码完成，模式数量:', encodedData.length);

      // 绘制条形码
      this.drawBarcode(canvas, encodedData, config);
      
      console.log('[JsBarcodeUtil] 条形码绘制完成');
      return true;

    } catch (error) {
      console.error('[JsBarcodeUtil] 生成条形码失败:', error);
      throw error;
    }
  }

  /**
   * Code 128B 编码
   * @param {string} text - 要编码的文本
   * @returns {Array} 编码后的模式数组
   */
  static encodeCode128B(text) {
    const codes = [];
    
    // Start Code B
    codes.push(104);
    
    // 数据字符
    let checksum = 104; // 起始码也参与校验和计算
    for (let i = 0; i < text.length; i++) {
      const char = text[i];
      const value = CODE128B_CHARS[char];
      codes.push(value);
      checksum += value * (i + 1); // 位置权重从1开始
    }
    
    // 校验码
    const checksumCode = checksum % 103;
    codes.push(checksumCode);
    
    // Stop Code
    codes.push(106);
    
    console.log('[JsBarcodeUtil] 编码序列:', codes);
    console.log('[JsBarcodeUtil] 校验和:', checksum, '校验码:', checksumCode);
    
    return codes;
  }

  /**
   * 绘制条形码
   * @param {Object} canvas - canvas对象
   * @param {Array} codes - 编码数组
   * @param {Object} config - 配置选项
   */
  static drawBarcode(canvas, codes, config) {
    const ctx = canvas.getContext('2d');
    
    // 计算总宽度
    let totalBars = 0;
    for (let code of codes) {
      const pattern = CODE128_PATTERNS[code];
      totalBars += pattern.length;
    }
    
    const canvasWidth = canvas.width;
    const canvasHeight = canvas.height;
    
    console.log('[JsBarcodeUtil] Canvas尺寸检查:', {
      canvasWidth,
      canvasHeight,
      totalBars
    });
    
    // 清除画布并设置背景
    ctx.fillStyle = config.background;
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
    
    // 计算条形码绘制区域
    const drawWidth = canvasWidth - config.marginLeft - config.marginRight;
    const drawHeight = canvasHeight - config.marginTop - config.marginBottom;
    const barWidth = drawWidth / totalBars;
    
    console.log('[JsBarcodeUtil] 绘制参数:', {
      canvasWidth,
      canvasHeight,
      drawWidth,
      drawHeight,
      totalBars,
      barWidth
    });
    
    // 绘制条形码
    ctx.fillStyle = config.lineColor;
    let x = config.marginLeft;
    
    for (let code of codes) {
      const pattern = CODE128_PATTERNS[code];
      
      for (let i = 0; i < pattern.length; i++) {
        if (pattern[i] === '1') {
          // 绘制黑条
          ctx.fillRect(x, config.marginTop, barWidth, drawHeight);
        }
        x += barWidth;
      }
    }
    
    // 如果需要显示文本
    if (config.displayValue) {
      this.drawText(ctx, codes, config, canvasWidth, canvasHeight);
    }
    
    // Canvas 2D API需要手动触发绘制
    // 注意：这里不需要调用draw()，因为Canvas 2D是实时绘制的
  }

  /**
   * 绘制文本
   * @param {Object} ctx - canvas上下文
   * @param {Array} codes - 编码数组  
   * @param {Object} config - 配置选项
   * @param {number} canvasWidth - 画布宽度
   * @param {number} canvasHeight - 画布高度
   */
  static drawText(ctx, codes, config, canvasWidth, canvasHeight) {
    // 从编码中还原文本（去掉起始码、校验码、停止码）
    let text = '';
    for (let i = 1; i < codes.length - 2; i++) {
      const code = codes[i];
      text += String.fromCharCode(code + 32);
    }
    
    ctx.fillStyle = config.lineColor;
    ctx.font = `${config.fontSize}px ${config.fontFamily}`;
    ctx.textAlign = config.textAlign;
    
    let textX = canvasWidth / 2;
    let textY;
    
    if (config.textPosition === 'top') {
      textY = config.marginTop - config.textMargin;
    } else {
      textY = canvasHeight - config.marginBottom + config.fontSize + config.textMargin;
    }
    
    ctx.fillText(text, textX, textY);
  }
}

module.exports = JsBarcodeUtil; 